winsafe\user\handles/
hwnd.rs

1#![allow(non_camel_case_types, non_snake_case)]
2
3use crate::co;
4use crate::decl::*;
5use crate::guard::*;
6use crate::kernel::privs::*;
7use crate::msg::*;
8use crate::prelude::*;
9use crate::user::{callbacks, ffi, privs::*};
10
11handle! { HWND;
12	/// Handle to a
13	/// [window](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#hwnd).
14}
15
16impl HWND {
17	/// Represents all top-level windows in
18	/// [`HWND::PostMessage`](crate::HWND::PostMessage) and
19	/// [`HWND::SendMessage`](crate::HWND::SendMessage).
20	pub const BROADCAST: HWND = HWND(0xffff as _);
21
22	/// Represents the desktop window in [`HWND::GetDC`](crate::HWND::GetDC).
23	pub const DESKTOP: HWND = HWND(std::ptr::null_mut());
24
25	/// Calls
26	/// [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to retrieve
27	/// the window [`HINSTANCE`](crate::HINSTANCE).
28	#[must_use]
29	pub fn hinstance(&self) -> HINSTANCE {
30		unsafe { HINSTANCE::from_ptr(self.GetWindowLongPtr(co::GWLP::HINSTANCE) as _) }
31	}
32
33	/// Calls
34	/// [`HWND::GetClassLongPtr`](crate::HWND::GetClassLongPtr) to retrieve the
35	/// [class atom](https://stackoverflow.com/a/64437627/6923555) and check
36	/// whether the window was created from a dialog resource.
37	#[must_use]
38	pub fn is_dialog(&self) -> bool {
39		self.GetClassLongPtr(co::GCLP::ATOM) as u16 == WC_DIALOG
40	}
41
42	/// Calls
43	/// [`HWND::SetWindowLongPtr`](crate::HWND::SetWindowLongPtr) to set the
44	/// window styles.
45	pub fn set_style(&self, style: impl Into<co::WS>) {
46		let style: co::WS = style.into();
47		unsafe {
48			self.SetWindowLongPtr(co::GWLP::STYLE, style.raw() as _);
49		}
50	}
51
52	/// Calls [`HWND::SetWindowLongPtr`](crate::HWND::SetWindowLongPtr) to set
53	/// the extended window styles.
54	pub fn set_style_ex(&self, ex_style: impl Into<co::WS_EX>) {
55		let ex_style: co::WS_EX = ex_style.into();
56		unsafe {
57			self.SetWindowLongPtr(co::GWLP::EXSTYLE, ex_style.raw() as _);
58		}
59	}
60
61	/// Calls [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to
62	/// retrieve the window styles.
63	#[must_use]
64	pub fn style(&self) -> co::WS {
65		unsafe { co::WS::from_raw(self.GetWindowLongPtr(co::GWLP::STYLE) as _) }
66	}
67
68	/// Calls [`HWND::GetWindowLongPtr`](crate::HWND::GetWindowLongPtr) to
69	/// retrieve the extended window styles.
70	#[must_use]
71	pub fn style_ex(&self) -> co::WS_EX {
72		unsafe { co::WS_EX::from_raw(self.GetWindowLongPtr(co::GWLP::EXSTYLE) as _) }
73	}
74
75	/// [`ArrangeIconicWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-arrangeiconicwindows)
76	/// function.
77	pub fn ArrangeIconicWindows(&self) -> SysResult<u32> {
78		match unsafe { ffi::ArrangeIconicWindows(self.ptr()) } {
79			0 => Err(GetLastError()),
80			height => Ok(height),
81		}
82	}
83
84	/// [`BeginPaint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-beginpaint)
85	/// function.
86	///
87	/// In the original C implementation, `BeginPaint` returns a handle which
88	/// must be passed to
89	/// [`EndPaint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-endpaint),
90	/// as a cleanup operation. Also, you must allocate and pass a
91	/// [`PAINTSTRUCT`](crate::PAINTSTRUCT) object.
92	///
93	/// Here, the cleanup is performed automatically, because `BeginPaint`
94	/// returns an [`EndPaintGuard`](crate::guard::EndPaintGuard), which stores
95	/// the `PAINTSTRUCT` and automatically calls `EndPaint` when the guard goes
96	/// out of scope. You must, however, keep the guard alive, otherwise the
97	/// cleanup will be performed right away.
98	///
99	/// # Examples
100	///
101	/// ```no_run
102	/// use winsafe::{self as w, prelude::*};
103	///
104	/// let hwnd: w::HWND; // initialized somewhere
105	/// # let hwnd = w::HWND::NULL;
106	///
107	/// let hdc = hwnd.BeginPaint()?;
108	///
109	/// // do your hdc painting...
110	///
111	/// // EndPaint() called automatically
112	/// # w::SysResult::Ok(())
113	/// ```
114	///
115	/// If you don't use the returned device context handle, you must still keep
116	/// the guard alive:
117	///
118	/// ```no_run
119	/// use winsafe::{self as w, prelude::*};
120	///
121	/// let hwnd: w::HWND; // initialized somewhere
122	/// # let hwnd = w::HWND::NULL;
123	///
124	/// let _hdc = hwnd.BeginPaint()?; // keep guard alive
125	///
126	/// // do your hdc painting...
127	///
128	/// // EndPaint() called automatically
129	/// # w::SysResult::Ok(())
130	/// ```
131	#[must_use]
132	pub fn BeginPaint(&self) -> SysResult<EndPaintGuard<'_>> {
133		let mut ps = PAINTSTRUCT::default();
134		unsafe {
135			ptr_to_sysresult_handle(ffi::BeginPaint(self.ptr(), pvoid(&mut ps)))
136				.map(|h| EndPaintGuard::new(self, h, ps))
137		}
138	}
139
140	/// [`BringWindowToTop`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-bringwindowtotop)
141	/// function.
142	pub fn BringWindowToTop(&self) -> SysResult<()> {
143		bool_to_sysresult(unsafe { ffi::BringWindowToTop(self.ptr()) })
144	}
145
146	/// [`ChildWindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-childwindowfrompoint)
147	/// function.
148	#[must_use]
149	pub fn ChildWindowFromPoint(&self, pt: POINT) -> Option<HWND> {
150		ptr_to_option_handle(unsafe { ffi::ChildWindowFromPoint(self.ptr(), pt.x, pt.y) })
151	}
152
153	/// [`ClientToScreen`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-clienttoscreen)
154	/// function.
155	///
156	/// If you need to convert a [`RECT`](crate::RECT), see the
157	/// [`HWND::ClientToScreenRc`](crate::HWND::ClientToScreenRc) function.
158	#[must_use]
159	pub fn ClientToScreen(&self, pt: POINT) -> SysResult<POINT> {
160		let mut buf = pt;
161		bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
162	}
163
164	/// [`ClientToScreen`](crate::HWND::ClientToScreen) method for a
165	/// [`RECT`](crate::RECT).
166	#[must_use]
167	pub fn ClientToScreenRc(&self, rc: RECT) -> SysResult<RECT> {
168		let mut buf = rc;
169		bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf.left)) })?;
170		bool_to_sysresult(unsafe { ffi::ClientToScreen(self.ptr(), pvoid(&mut buf.right)) })
171			.map(|_| buf)
172	}
173
174	/// [`CloseWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-closewindow)
175	/// function.
176	///
177	/// Note that this method will actually minimize the window, not destroy it.
178	pub fn CloseWindow(&self) -> SysResult<()> {
179		bool_to_sysresult(unsafe { ffi::CloseWindow(self.ptr()) })
180	}
181
182	/// [`CreateWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw)
183	/// function.
184	///
185	/// # Safety
186	///
187	/// This method will create raw dynamic windows and controls outside the
188	/// library safety – it's up to you to handle all the messages. You must use
189	/// a properly registered class name and, if creating a custom window,
190	/// provide its own window procedure.
191	///
192	/// The usable ID range for child controls is
193	/// [8 to 57,343](https://stackoverflow.com/a/18192766/6923555).
194	pub unsafe fn CreateWindowEx(
195		ex_style: co::WS_EX,
196		class_name: AtomStr,
197		title: Option<&str>,
198		style: co::WS,
199		pos: POINT,
200		size: SIZE,
201		hwnd_parent: Option<&HWND>,
202		hmenu: IdMenu,
203		hinstance: &HINSTANCE,
204		lparam: Option<isize>,
205	) -> SysResult<HWND> {
206		ptr_to_sysresult_handle(unsafe {
207			ffi::CreateWindowExW(
208				ex_style.raw(),
209				class_name.as_ptr(),
210				WString::from_opt_str(title).as_ptr(),
211				style.raw(),
212				pos.x,
213				pos.y,
214				size.cx,
215				size.cy,
216				hwnd_parent.map_or(std::ptr::null_mut(), |h| h.ptr()),
217				hmenu.as_ptr(),
218				hinstance.ptr(),
219				lparam.unwrap_or_default() as _,
220			)
221		})
222	}
223
224	/// [`DefWindowProc`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw)
225	/// function.
226	///
227	/// The return type is variable, being defined by the `RetType` associated
228	/// type of the [`MsgSend`](crate::prelude::MsgSend) trait. That means each
229	/// message can define its own return type.
230	///
231	/// # Safety
232	///
233	/// Messages manipulate pointers, copies and window states. Improper use may
234	/// lead to undefined behavior.
235	pub unsafe fn DefWindowProc<M>(&self, msg: M) -> M::RetType
236	where
237		M: MsgSend,
238	{
239		let mut msg = msg;
240		let wm_any = msg.as_generic_wm();
241		unsafe {
242			msg.isize_to_ret(ffi::DefWindowProcW(
243				self.ptr(),
244				wm_any.msg_id.raw(),
245				wm_any.wparam,
246				wm_any.lparam,
247			))
248		}
249	}
250
251	/// [`DestroyWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow)
252	/// function.
253	///
254	/// Usually you don't need to call this method directly, since it's
255	/// automatically called inside the internal message loop. The ordinary way
256	/// to close a window is sending a [`wm::Close`](crate::msg::wm::Close)
257	/// message.
258	pub fn DestroyWindow(&self) -> SysResult<()> {
259		bool_to_sysresult(unsafe { ffi::DestroyWindow(self.ptr()) })
260	}
261
262	/// [`DragDetect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dragdetect)
263	/// function.
264	#[must_use]
265	pub fn DragDetect(&self, pt: POINT) -> bool {
266		unsafe { ffi::DragDetect(self.ptr(), pt.x, pt.y) != 0 }
267	}
268
269	/// [`DrawCaption`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawcaption)
270	/// function.
271	pub fn DrawCaption(&self, hdc: &HDC, rect: RECT, flags: Option<co::DC>) -> SysResult<()> {
272		bool_to_sysresult(unsafe {
273			ffi::DrawCaption(self.ptr(), hdc.ptr(), pcvoid(&rect), flags.unwrap_or_default().raw())
274		})
275	}
276
277	/// [`DrawMenuBar`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawmenubar)
278	/// function.
279	pub fn DrawMenuBar(&self) -> SysResult<()> {
280		bool_to_sysresult(unsafe { ffi::DrawMenuBar(self.ptr()) })
281	}
282
283	/// [`EnableScrollBar`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablescrollbar)
284	/// function.
285	pub fn EnableScrollBar(&self, sb_flags: co::SBB, arrows: co::ESB) -> SysResult<()> {
286		bool_to_sysresult(unsafe {
287			ffi::EnableScrollBar(self.ptr(), sb_flags.raw() as _, arrows.raw())
288		})
289	}
290
291	/// [`EnableWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enablewindow)
292	/// function.
293	pub fn EnableWindow(&self, enable: bool) -> bool {
294		unsafe { ffi::EnableWindow(self.ptr(), enable as _) != 0 }
295	}
296
297	/// [`EndDialog`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enddialog)
298	/// function.
299	pub fn EndDialog(&self, result: isize) -> SysResult<()> {
300		bool_to_sysresult(unsafe { ffi::EndDialog(self.ptr(), result) })
301	}
302
303	/// [`EnumChildWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumchildwindows)
304	/// function.
305	///
306	/// # Examples
307	///
308	/// ```no_run
309	/// use winsafe::{self as w, prelude::*};
310	///
311	/// let hwnd: w::HWND; // initialized somewhere
312	/// # let hwnd = w::HWND::NULL;
313	///
314	/// hwnd.EnumChildWindows(|hchild: w::HWND| -> bool {
315	///     println!("Child HWND: {}", hchild);
316	///     true
317	/// });
318	/// ```
319	pub fn EnumChildWindows<F>(&self, func: F)
320	where
321		F: FnMut(HWND) -> bool,
322	{
323		unsafe {
324			ffi::EnumChildWindows(
325				self.ptr(),
326				callbacks::hwnd_enum_child_windows::<F> as _, // https://redd.it/npehj9
327				pcvoid(&func),
328			);
329		}
330	}
331
332	/// [`FindWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindoww)
333	/// function.
334	#[must_use]
335	pub fn FindWindow(class_name: Option<AtomStr>, title: Option<&str>) -> SysResult<Option<HWND>> {
336		let ptr = unsafe {
337			ffi::FindWindowW(
338				class_name.as_ref().map_or(std::ptr::null(), |c| c.as_ptr()),
339				WString::from_opt_str(title).as_ptr(),
340			)
341		};
342
343		if ptr.is_null() {
344			match GetLastError() {
345				co::ERROR::SUCCESS => Ok(None), // no window found
346				err => Err(err),                // actual error
347			}
348		} else {
349			Ok(Some(unsafe { HWND::from_ptr(ptr) }))
350		}
351	}
352
353	/// [`FindWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw)
354	/// function.
355	#[must_use]
356	pub fn FindWindowEx(
357		&self,
358		hwnd_child_after: Option<&HWND>,
359		class_name: AtomStr,
360		title: Option<&str>,
361	) -> SysResult<Option<HWND>> {
362		let ptr = unsafe {
363			ffi::FindWindowExW(
364				self.ptr(),
365				hwnd_child_after.map_or(std::ptr::null_mut(), |h| h.ptr()),
366				class_name.as_ptr(),
367				WString::from_opt_str(title).as_ptr(),
368			)
369		};
370
371		if ptr.is_null() {
372			match GetLastError() {
373				co::ERROR::SUCCESS => Ok(None), // no window found
374				err => Err(err),                // actual error
375			}
376		} else {
377			Ok(Some(unsafe { HWND::from_ptr(ptr) }))
378		}
379	}
380
381	/// [`GetActiveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getactivewindow)
382	/// function.
383	#[must_use]
384	pub fn GetActiveWindow() -> Option<HWND> {
385		ptr_to_option_handle(unsafe { ffi::GetActiveWindow() })
386	}
387
388	/// [`GetAltTabInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getalttabinfow)
389	/// function.
390	///
391	/// If `item` is `None`, the item text is not retrieved.
392	///
393	/// The `sz_item_text` is the maximum number of expected chars for the item
394	/// text. If `None`, defaults to 100.
395	pub fn GetAltTabInfo(
396		&self,
397		item: Option<u32>,
398		ati: &mut ALTTABINFO,
399		sz_item_text: Option<u32>,
400	) -> SysResult<String> {
401		let buf_sz = sz_item_text.unwrap_or(100) + 1;
402		let mut buf = match item {
403			None => WString::new(),
404			Some(_) => WString::new_alloc_buf(buf_sz as _), // room for terminating null
405		};
406
407		bool_to_sysresult(unsafe {
408			ffi::GetAltTabInfoW(
409				self.ptr(),
410				item.map_or(-1, |item| item as i32),
411				pvoid(ati),
412				item.map_or(std::ptr::null_mut(), |_| buf.as_mut_ptr()),
413				buf_sz,
414			)
415		})
416		.map(|_| buf.to_string())
417	}
418
419	/// [`GetAncestor`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getancestor)
420	/// function.
421	#[must_use]
422	pub fn GetAncestor(&self, flags: co::GA) -> Option<HWND> {
423		ptr_to_option_handle(unsafe { ffi::GetAncestor(self.ptr(), flags.raw()) })
424	}
425
426	/// [`GetCapture`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcapture)
427	/// function.
428	#[must_use]
429	pub fn GetCapture() -> Option<HWND> {
430		ptr_to_option_handle(unsafe { ffi::GetCapture() })
431	}
432
433	/// [`GetClassLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclasslongptrw)
434	/// function.
435	///
436	/// If you just want to check whether the window is a dialog, prefer using
437	/// [`HWND::is_dialog`](crate::HWND::is_dialog) method.
438	#[must_use]
439	pub fn GetClassLongPtr(&self, index: co::GCLP) -> usize {
440		unsafe { ffi::GetClassLongPtrW(self.ptr(), index.raw()) }
441	}
442
443	/// [`GetClassName`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassnamew)
444	/// function.
445	#[must_use]
446	pub fn GetClassName(&self) -> SysResult<String> {
447		let mut buf = WString::new_alloc_buf(256 + 1); // according to WNDCLASSEX docs
448		bool_to_sysresult(unsafe {
449			ffi::GetClassNameW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as _)
450		})
451		.map(|_| buf.to_string())
452	}
453
454	/// [`GetClientRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect)
455	/// function.
456	#[must_use]
457	pub fn GetClientRect(&self) -> SysResult<RECT> {
458		let mut rc = RECT::default();
459		bool_to_sysresult(unsafe { ffi::GetClientRect(self.ptr(), pvoid(&mut rc)) }).map(|_| rc)
460	}
461
462	/// [`GetDC`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
463	/// function.
464	///
465	/// # Examples
466	///
467	/// Retrieving the device context of the desktop window:
468	///
469	/// ```no_run
470	/// use winsafe::{self as w, prelude::*};
471	///
472	/// let hdc_desktop = w::HWND::DESKTOP.GetDC()?;
473	/// # w::SysResult::Ok(())
474	/// ```
475	#[must_use]
476	pub fn GetDC(&self) -> SysResult<ReleaseDCGuard<'_>> {
477		unsafe {
478			ptr_to_sysresult_handle(ffi::GetDC(self.ptr())).map(|h| ReleaseDCGuard::new(self, h))
479		}
480	}
481
482	/// [`GetDCEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdcex)
483	/// function.
484	#[must_use]
485	pub fn GetDCEx(&self, hrgn_clip: &HRGN, flags: co::DCX) -> SysResult<ReleaseDCGuard<'_>> {
486		unsafe {
487			ptr_to_sysresult_handle(ffi::GetDCEx(self.ptr(), hrgn_clip.ptr(), flags.raw()))
488				.map(|h| ReleaseDCGuard::new(self, h))
489		}
490	}
491
492	/// [`GetDesktopWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdesktopwindow)
493	/// function.
494	#[must_use]
495	pub fn GetDesktopWindow() -> HWND {
496		unsafe { HWND::from_ptr(ffi::GetDesktopWindow()) }
497	}
498
499	/// [`GetDialogDpiChangeBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdialogdpichangebehavior)
500	/// function.
501	#[must_use]
502	pub fn GetDialogDpiChangeBehavior(&self) -> SysResult<co::DDC> {
503		match unsafe { co::DDC::from_raw(ffi::GetDialogDpiChangeBehavior(self.ptr())) } {
504			co::DDC::DEFAULT => match GetLastError() {
505				co::ERROR::SUCCESS => Ok(co::DDC::DEFAULT), // actual return value is zero
506				err => Err(err),
507			},
508			ddc => Ok(ddc),
509		}
510	}
511
512	/// [`GetDlgCtrlID`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdlgctrlid)
513	/// function.
514	#[must_use]
515	pub fn GetDlgCtrlID(&self) -> SysResult<u16> {
516		SetLastError(co::ERROR::SUCCESS);
517		match unsafe { ffi::GetDlgCtrlID(self.ptr()) } {
518			0 => match GetLastError() {
519				co::ERROR::SUCCESS => Ok(0), // actual ID is zero
520				err => Err(err),
521			},
522			id => Ok(id as _),
523		}
524	}
525
526	/// [`GetDlgItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdlgitem)
527	/// function.
528	#[must_use]
529	pub fn GetDlgItem(&self, ctrl_id: u16) -> SysResult<HWND> {
530		ptr_to_sysresult_handle(unsafe { ffi::GetDlgItem(self.ptr(), ctrl_id as _) })
531	}
532
533	/// [`GetDpiForWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow)
534	/// function.
535	#[must_use]
536	pub fn GetDpiForWindow(&self) -> u32 {
537		unsafe { ffi::GetDpiForWindow(self.ptr()) }
538	}
539
540	/// [`GetFocus`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getfocus)
541	/// function.
542	#[must_use]
543	pub fn GetFocus() -> Option<HWND> {
544		ptr_to_option_handle(unsafe { ffi::GetFocus() })
545	}
546
547	/// [`GetForegroundWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getforegroundwindow)
548	/// function.
549	#[must_use]
550	pub fn GetForegroundWindow() -> Option<HWND> {
551		ptr_to_option_handle(unsafe { ffi::GetForegroundWindow() })
552	}
553
554	/// [`GetLastActivePopup`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getlastactivepopup)
555	/// function.
556	#[must_use]
557	pub fn GetLastActivePopup(&self) -> Option<HWND> {
558		ptr_to_option_handle(unsafe { ffi::GetLastActivePopup(self.ptr()) })
559	}
560
561	/// [`GetMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenu)
562	/// function.
563	#[must_use]
564	pub fn GetMenu(&self) -> Option<HMENU> {
565		ptr_to_option_handle(unsafe { ffi::GetMenu(self.ptr()) })
566	}
567
568	/// [`GetMenuBarInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenubarinfo)
569	/// function.
570	pub fn GetMenuBarInfo(
571		&self,
572		obj_id: co::OBJID,
573		item_id: u32,
574		mbi: &mut MENUBARINFO,
575	) -> SysResult<()> {
576		bool_to_sysresult(unsafe {
577			ffi::GetMenuBarInfo(self.ptr(), obj_id.raw() as _, item_id as _, pvoid(mbi))
578		})
579	}
580
581	/// [`GetMenuItemRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenuitemrect)
582	/// function.
583	#[must_use]
584	pub fn GetMenuItemRect(&self, hmenu: &HMENU, item_pos: u32) -> SysResult<RECT> {
585		let mut rc = RECT::default();
586		bool_to_sysresult(unsafe {
587			ffi::GetMenuItemRect(self.ptr(), hmenu.ptr(), item_pos, pvoid(&mut rc))
588		})
589		.map(|_| rc)
590	}
591
592	/// [`GetNextDlgGroupItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getnextdlggroupitem)
593	/// function.
594	#[must_use]
595	pub fn GetNextDlgGroupItem(&self, hwnd_ctrl: &HWND, previous: bool) -> SysResult<HWND> {
596		ptr_to_sysresult_handle(unsafe {
597			ffi::GetNextDlgGroupItem(self.ptr(), hwnd_ctrl.ptr(), previous as _)
598		})
599	}
600
601	/// [`GetNextDlgTabItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getnextdlgtabitem)
602	/// function.
603	#[must_use]
604	pub fn GetNextDlgTabItem(&self, hwnd_ctrl: &HWND, previous: bool) -> SysResult<HWND> {
605		ptr_to_sysresult_handle(unsafe {
606			ffi::GetNextDlgTabItem(self.ptr(), hwnd_ctrl.ptr(), previous as _)
607		})
608	}
609
610	/// [`GetParent`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getparent)
611	/// function.
612	#[must_use]
613	pub fn GetParent(&self) -> SysResult<HWND> {
614		ptr_to_sysresult_handle(unsafe { ffi::GetParent(self.ptr()) })
615	}
616
617	/// [`GetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getscrollinfo)
618	/// function.
619	pub fn GetScrollInfo(&self, bar: co::SBB, si: &mut SCROLLINFO) -> SysResult<()> {
620		bool_to_sysresult(unsafe { ffi::GetScrollInfo(self.ptr(), bar.raw(), pvoid(si)) })
621	}
622
623	/// [`GetScrollPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getscrollpos)
624	/// function.
625	#[must_use]
626	pub fn GetScrollPos(&self, bar: co::SBB) -> SysResult<i32> {
627		match unsafe { ffi::GetScrollPos(self.ptr(), bar.raw()) } {
628			0 => match GetLastError() {
629				co::ERROR::SUCCESS => Ok(0), // actual zero position
630				err => Err(err),
631			},
632			pos => Ok(pos),
633		}
634	}
635
636	/// [`GetShellWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getshellwindow)
637	/// function.
638	#[must_use]
639	pub fn GetShellWindow() -> Option<HWND> {
640		ptr_to_option_handle(unsafe { ffi::GetShellWindow() })
641	}
642
643	/// [`GetSystemMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmenu)
644	/// function.
645	#[must_use]
646	pub fn GetSystemMenu(&self, revert: bool) -> Option<HMENU> {
647		ptr_to_option_handle(unsafe { ffi::GetSystemMenu(self.ptr(), revert as _) })
648	}
649
650	/// [`GetTopWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-gettopwindow)
651	/// function.
652	#[must_use]
653	pub fn GetTopWindow(&self) -> SysResult<Option<HWND>> {
654		match ptr_to_option_handle(unsafe { ffi::GetTopWindow(self.ptr()) }) {
655			None => match GetLastError() {
656				co::ERROR::SUCCESS => Ok(None), // no child window
657				err => Err(err),
658			},
659			Some(h) => Ok(Some(h)),
660		}
661	}
662
663	/// [`GetUpdateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getupdaterect)
664	/// function.
665	#[must_use]
666	pub fn GetUpdateRect(&self, erase: bool) -> Option<RECT> {
667		let mut rc = RECT::default();
668		zero_as_none(unsafe { ffi::GetUpdateRect(self.ptr(), pvoid(&mut rc), erase as _) } as _)
669			.map(|_| rc)
670	}
671
672	/// [`GetUpdateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getupdatergn)
673	/// function.
674	#[must_use]
675	pub fn GetUpdateRgn(&self, hrgn: &HRGN, erase: bool) -> SysResult<co::REGION> {
676		match unsafe { ffi::GetUpdateRgn(self.ptr(), hrgn.ptr(), erase as _) } {
677			0 => Err(GetLastError()),
678			ret => Ok(unsafe { co::REGION::from_raw(ret) }),
679		}
680	}
681
682	/// [`GetWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindow)
683	/// function.
684	#[must_use]
685	pub fn GetWindow(&self, cmd: co::GW) -> SysResult<HWND> {
686		ptr_to_sysresult_handle(unsafe { ffi::GetWindow(self.ptr(), cmd.raw()) })
687	}
688
689	/// [`GetWindowDC`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdc)
690	/// function.
691	#[must_use]
692	pub fn GetWindowDC(&self) -> SysResult<ReleaseDCGuard<'_>> {
693		unsafe {
694			ptr_to_sysresult_handle(ffi::GetWindowDC(self.ptr()))
695				.map(|h| ReleaseDCGuard::new(self, h))
696		}
697	}
698
699	/// [`GetWindowDisplayAffinity`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdisplayaffinity)
700	/// function.
701	#[must_use]
702	pub fn GetWindowDisplayAffinity(&self) -> SysResult<co::WDA> {
703		let mut affinity = co::WDA::default();
704		bool_to_sysresult(unsafe {
705			ffi::GetWindowDisplayAffinity(self.ptr(), pvoid(&mut affinity))
706		})
707		.map(|_| affinity)
708	}
709
710	/// [`GetWindowDpiHostingBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpihostingbehavior)
711	/// function.
712	#[must_use]
713	pub fn GetWindowDpiHostingBehavior(&self) -> co::DPI_HOSTING_BEHAVIOR {
714		unsafe { co::DPI_HOSTING_BEHAVIOR::from_raw(ffi::GetWindowDpiHostingBehavior(self.ptr())) }
715	}
716
717	/// [`GetWindowInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowinfo)
718	/// function.
719	pub fn GetWindowInfo(&self, wi: &mut WINDOWINFO) -> SysResult<()> {
720		bool_to_sysresult(unsafe { ffi::GetWindowInfo(self.ptr(), pvoid(wi)) })
721	}
722
723	/// [`GetWindowLong`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongw)
724	/// function (x32) or
725	/// [`GetWindowLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw)
726	/// function (x64).
727	///
728	/// If you just want to retrieve the window [`HINSTANCE`](crate::HINSTANCE),
729	/// prefer using [`HWND::hinstance`](crate::HWND::hinstance).
730	///
731	/// If you just want to retrieve the window styles, prefer using
732	/// [`HWND::style`](crate::HWND::style) and
733	/// [`HWND::style_ex`](crate::HWND::style_ex).
734	#[must_use]
735	pub fn GetWindowLongPtr(&self, index: co::GWLP) -> isize {
736		#[cfg(target_pointer_width = "32")]
737		unsafe {
738			ffi::GetWindowLongW(self.ptr(), index.raw())
739		}
740
741		#[cfg(target_pointer_width = "64")]
742		unsafe {
743			ffi::GetWindowLongPtrW(self.ptr(), index.raw())
744		}
745	}
746
747	/// [`GetWindowModuleFileName`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowmodulefilenamew)
748	/// function.
749	#[must_use]
750	pub fn GetWindowModuleFileName(&self) -> String {
751		let mut buf = WString::new_alloc_buf(MAX_PATH + 1);
752		unsafe {
753			ffi::GetWindowModuleFileNameW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as u32 - 1);
754		}
755		buf.to_string()
756	}
757
758	/// [`GetWindowPlacement`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowplacement)
759	/// function.
760	pub fn GetWindowPlacement(&self, wp: &mut WINDOWPLACEMENT) -> SysResult<()> {
761		bool_to_sysresult(unsafe { ffi::GetWindowPlacement(self.ptr(), pvoid(wp)) })
762	}
763
764	/// [`GetWindowRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect)
765	/// function.
766	#[must_use]
767	pub fn GetWindowRect(&self) -> SysResult<RECT> {
768		let mut rc = RECT::default();
769		bool_to_sysresult(unsafe { ffi::GetWindowRect(self.ptr(), pvoid(&mut rc)) }).map(|_| rc)
770	}
771
772	/// [`GetWindowRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrgn)
773	/// function.
774	#[must_use]
775	pub fn GetWindowRgn(&self, hrgn: &HRGN) -> SysResult<co::REGION> {
776		match unsafe { ffi::GetWindowRgn(self.ptr(), hrgn.ptr()) } {
777			0 => Err(GetLastError()),
778			ret => Ok(unsafe { co::REGION::from_raw(ret) }),
779		}
780	}
781
782	/// [`GetWindowRgnBox`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrgnbox)
783	/// function.
784	#[must_use]
785	pub fn GetWindowRgnBox(&self) -> SysResult<(RECT, co::REGION)> {
786		let mut rc = RECT::default();
787		match unsafe { ffi::GetWindowRgnBox(self.ptr(), pvoid(&mut rc)) } {
788			0 => Err(GetLastError()),
789			ret => Ok((rc, unsafe { co::REGION::from_raw(ret) })),
790		}
791	}
792
793	/// [`GetWindowText`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw)
794	/// function.
795	///
796	/// Calls
797	/// [`GetWindowTextLength`](crate::HWND::GetWindowTextLength) and performs
798	/// all necessary allocations, returning an ordinary
799	/// [`String`](std::string::String).
800	///
801	/// ```no_run
802	/// use winsafe::{self as w, prelude::*};
803	///
804	/// let hwnd: w::HWND; // initialized somewhere
805	/// # let hwnd = w::HWND::NULL;
806	///
807	/// let text = hwnd.GetWindowText()?;
808	/// println!("Text: {}", text);
809	/// # w::SysResult::Ok(())
810	/// ```
811	#[must_use]
812	pub fn GetWindowText(&self) -> SysResult<String> {
813		let len = self.GetWindowTextLength()?;
814		if len == 0 {
815			return Ok(String::new()); // window has no text
816		}
817
818		let mut buf = WString::new_alloc_buf(len as usize + 1); // plus terminating null
819		match unsafe { ffi::GetWindowTextW(self.ptr(), buf.as_mut_ptr(), len + 1) } {
820			0 => match GetLastError() {
821				co::ERROR::SUCCESS => Ok(String::new()), // no chars copied for some reason
822				err => Err(err),
823			},
824			_ => Ok(buf.to_string()),
825		}
826	}
827
828	/// [`GetWindowTextLength`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextlengthw)
829	/// function.
830	///
831	/// Does not count the terminating null.
832	///
833	/// You usually don't need to call this method directly, since
834	/// [`GetWindowText`](crate::HWND::GetWindowText) returns a
835	/// [`String`](std::string::String), performing all necessary allocations.
836	#[must_use]
837	pub fn GetWindowTextLength(&self) -> SysResult<i32> {
838		SetLastError(co::ERROR::SUCCESS);
839		match unsafe { ffi::GetWindowTextLengthW(self.ptr()) } {
840			0 => match GetLastError() {
841				co::ERROR::SUCCESS => Ok(0), // actual zero length
842				err => Err(err),
843			},
844			len => Ok(len),
845		}
846	}
847
848	/// [`GetWindowThreadProcessId`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowthreadprocessid)
849	/// function.
850	///
851	/// Returns thread ID and process ID, respectively.
852	#[must_use]
853	pub fn GetWindowThreadProcessId(&self) -> (u32, u32) {
854		let mut proc_id = 0u32;
855		let thread_id = unsafe { ffi::GetWindowThreadProcessId(self.ptr(), &mut proc_id) };
856		(thread_id, proc_id)
857	}
858
859	/// [`HideCaret`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-hidecaret)
860	/// function.
861	pub fn HideCaret(&self) -> SysResult<()> {
862		bool_to_sysresult(unsafe { ffi::HideCaret(self.ptr()) })
863	}
864
865	/// [`HiliteMenuItem`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-hilitemenuitem)
866	/// function.
867	pub fn HiliteMenuItem(&self, hmenu: &HMENU, id_or_pos: IdPos, hilite: bool) -> bool {
868		unsafe {
869			ffi::HiliteMenuItem(
870				self.ptr(),
871				hmenu.ptr(),
872				id_or_pos.id_or_pos_u32(),
873				id_or_pos.mf_flag().raw()
874					| if hilite { co::MF::HILITE } else { co::MF::UNHILITE }.raw(),
875			) != 0
876		}
877	}
878
879	/// [`InheritWindowMonitor`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-inheritwindowmonitor)
880	/// function.
881	pub fn InheritWindowMonitor(&self, hwnd_inherit: &HWND) -> SysResult<()> {
882		bool_to_sysresult(unsafe { ffi::InheritWindowMonitor(self.ptr(), hwnd_inherit.ptr()) })
883	}
884
885	/// [`InvalidateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidaterect)
886	/// function.
887	///
888	/// # Examples
889	///
890	/// Most of the time you'll just want update the entire client area:
891	///
892	/// ```no_run
893	/// use winsafe::{self as w, prelude::*};
894	///
895	/// let hwnd: w::HWND; // initialized somewhere
896	/// # let hwnd = w::HWND::NULL;
897	///
898	/// hwnd.InvalidateRect(None, true)?;
899	/// # w::SysResult::Ok(())
900	/// ```
901	pub fn InvalidateRect(&self, rc: Option<&RECT>, erase: bool) -> SysResult<()> {
902		bool_to_sysresult(unsafe {
903			ffi::InvalidateRect(self.ptr(), pcvoid_or_null(rc), erase as _)
904		})
905	}
906
907	/// [`InvalidateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidatergn)
908	/// function.
909	pub fn InvalidateRgn(&self, hrgn: &HRGN, erase: bool) {
910		unsafe {
911			ffi::InvalidateRgn(self.ptr(), hrgn.ptr(), erase as _);
912		}
913	}
914
915	/// [`IsChild`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-ischild)
916	/// function.
917	#[must_use]
918	pub fn IsChild(&self, hwnd_possible_child: &HWND) -> bool {
919		unsafe { ffi::IsChild(self.ptr(), hwnd_possible_child.ptr()) != 0 }
920	}
921
922	/// [`IsDialogMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isdialogmessagew)
923	/// function.
924	#[must_use]
925	pub fn IsDialogMessage(&self, msg: &mut MSG) -> bool {
926		unsafe { ffi::IsDialogMessageW(self.ptr(), pvoid(msg)) != 0 }
927	}
928
929	/// [`IsIconic`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isiconic)
930	/// function.
931	#[must_use]
932	pub fn IsIconic(&self) -> bool {
933		unsafe { ffi::IsIconic(self.ptr()) != 0 }
934	}
935
936	/// [`IsWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindow)
937	/// function.
938	#[must_use]
939	pub fn IsWindow(&self) -> bool {
940		unsafe { ffi::IsWindow(self.ptr()) != 0 }
941	}
942
943	/// [`IsWindowEnabled`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowenabled)
944	/// function.
945	#[must_use]
946	pub fn IsWindowEnabled(&self) -> bool {
947		unsafe { ffi::IsWindowEnabled(self.ptr()) != 0 }
948	}
949
950	/// [`IsWindowUnicode`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowunicode)
951	/// function.
952	#[must_use]
953	pub fn IsWindowUnicode(&self) -> bool {
954		unsafe { ffi::IsWindowUnicode(self.ptr()) != 0 }
955	}
956
957	/// [`IsWindowVisible`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iswindowvisible)
958	/// function.
959	#[must_use]
960	pub fn IsWindowVisible(&self) -> bool {
961		unsafe { ffi::IsWindowVisible(self.ptr()) != 0 }
962	}
963
964	/// [`IsZoomed`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-iszoomed)
965	/// function.
966	#[must_use]
967	pub fn IsZoomed(&self) -> bool {
968		unsafe { ffi::IsZoomed(self.ptr()) != 0 }
969	}
970
971	/// [`KillTimer`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-killtimer)
972	/// function.
973	///
974	/// This function ends the timer calls for the given timer ID. If you don't
975	/// call this function, the timer calls will continue until the window is
976	/// destroyed – at this point, any remaining timers will be automatically
977	/// cleared.
978	pub fn KillTimer(&self, event_id: usize) -> SysResult<()> {
979		match unsafe { ffi::KillTimer(self.ptr(), event_id) } {
980			0 => match GetLastError() {
981				co::ERROR::SUCCESS => Ok(()),
982				e => Err(e),
983			},
984			_ => Ok(()),
985		}
986	}
987
988	/// [`LockWindowUpdate`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-lockwindowupdate)
989	/// function.
990	///
991	/// # Examples
992	///
993	/// ```no_run
994	/// use winsafe::{self as w, prelude::*};
995	///
996	/// let hwnd: w::HWND; // initialized somewhere
997	/// # let hwnd = w::HWND::NULL;
998	///
999	/// // Lock the window – only one window can be locked at a time.
1000	/// hwnd.LockWindowUpdate()?;
1001	///
1002	/// // After all operations, unlock the currently locked window.
1003	/// w::HWND::NULL.LockWindowUpdate()?;
1004	/// # w::SysResult::Ok(())
1005	/// ```
1006	pub fn LockWindowUpdate(&self) -> SysResult<()> {
1007		bool_to_sysresult(unsafe { ffi::LockWindowUpdate(self.ptr()) })
1008	}
1009
1010	/// [`LogicalToPhysicalPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-logicaltophysicalpoint)
1011	/// function.
1012	pub fn LogicalToPhysicalPoint(&self, pt: *mut POINT) -> SysResult<()> {
1013		bool_to_sysresult(unsafe { ffi::LogicalToPhysicalPoint(self.ptr(), pt as _) })
1014	}
1015
1016	/// [`MapDialogRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapdialogrect)
1017	/// function.
1018	#[must_use]
1019	pub fn MapDialogRect(&self, rc: RECT) -> SysResult<RECT> {
1020		let mut buf = rc;
1021		bool_to_sysresult(unsafe { ffi::MapDialogRect(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
1022	}
1023
1024	/// [`MapWindowPoints`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapwindowpoints)
1025	/// function.
1026	///
1027	/// This method can convert either a series of [`POINT`](crate::POINT)
1028	/// structs or a single [`RECT`](crate::RECT).
1029	///
1030	/// # Examples
1031	///
1032	/// ```no_run
1033	/// use winsafe::{self as w, prelude::*};
1034	///
1035	/// let hwnd: w::HWND; // initialized somewhere
1036	/// # let hwnd = w::HWND::NULL;
1037	/// let hwnd_dest: w::HWND;
1038	/// # let hwnd_dest = w::HWND::NULL;
1039	///
1040	/// let mut points = vec![w::POINT::default(), w::POINT::default()];
1041	///
1042	/// hwnd.MapWindowPoints(
1043	///     &hwnd_dest,
1044	///     w::PtsRc::Pts(&mut points),
1045	/// )?;
1046	/// # w::SysResult::Ok(())
1047	/// ```
1048	pub fn MapWindowPoints(&self, hdest: &HWND, points: PtsRc) -> SysResult<(i16, i16)> {
1049		let forced_pts = match points {
1050			PtsRc::Pts(pts) => pts,
1051			PtsRc::Rc(rc) => unsafe { std::slice::from_raw_parts_mut(rc as *mut _ as _, 2) },
1052		};
1053
1054		SetLastError(co::ERROR::SUCCESS);
1055		match unsafe {
1056			ffi::MapWindowPoints(
1057				self.ptr(),
1058				hdest.ptr(),
1059				forced_pts.as_mut_ptr() as _,
1060				forced_pts.len() as _,
1061			)
1062		} {
1063			0 => Err(GetLastError()),
1064			n => Ok((LOWORD(n as _) as _, HIWORD(n as _) as _)),
1065		}
1066	}
1067
1068	/// [`MessageBox`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw)
1069	/// function.
1070	///
1071	/// Consider using the more modern
1072	/// [`HWND::TaskDialog`](crate::HWND::TaskDialog) method.
1073	///
1074	/// # Examples
1075	///
1076	/// A modal message box, which blocks its parent:
1077	///
1078	/// ```no_run
1079	/// use winsafe::{self as w, prelude::*, co};
1080	///
1081	/// let hwnd: w::HWND; // initialized somewhere
1082	/// # let hwnd = w::HWND::NULL;
1083	///
1084	/// hwnd.MessageBox("Hello, world", "title",
1085	///     co::MB::OKCANCEL | co::MB::ICONINFORMATION)?;
1086	/// # w::SysResult::Ok(())
1087	/// ```
1088	///
1089	/// Usually the message box has a valid parent window, however, if for some
1090	/// reason you don't have a window to serve as parent, you still can show a
1091	/// non-modal, parent-less message box by using the null window handle:
1092	///
1093	/// ```no_run
1094	/// use winsafe::{self as w, prelude::*, co};
1095	///
1096	/// w::HWND::NULL
1097	///     .MessageBox("Hello, world", "Title", co::MB::ICONEXCLAMATION)?;
1098	/// # w::SysResult::Ok(())
1099	/// ```
1100	pub fn MessageBox(&self, text: &str, caption: &str, flags: co::MB) -> SysResult<co::DLGID> {
1101		match unsafe {
1102			ffi::MessageBoxW(
1103				self.ptr(),
1104				WString::from_str(text).as_ptr(),
1105				WString::from_str(caption).as_ptr(),
1106				flags.raw(),
1107			)
1108		} {
1109			0 => Err(GetLastError()),
1110			ret => Ok(unsafe { co::DLGID::from_raw(ret as _) }),
1111		}
1112	}
1113
1114	/// [`MonitorFromWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow)
1115	/// function.
1116	#[must_use]
1117	pub fn MonitorFromWindow(&self, flags: co::MONITOR) -> HMONITOR {
1118		unsafe { HMONITOR::from_ptr(ffi::MonitorFromWindow(self.ptr(), flags.raw())) }
1119	}
1120
1121	/// [`MoveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-movewindow)
1122	/// function.
1123	pub fn MoveWindow(&self, pos: POINT, size: SIZE, repaint: bool) -> SysResult<()> {
1124		bool_to_sysresult(unsafe {
1125			ffi::MoveWindow(self.ptr(), pos.x, pos.y, size.cx, size.cy, repaint as _)
1126		})
1127	}
1128
1129	/// [`OpenClipboard`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-openclipboard)
1130	/// function.
1131	///
1132	/// In the original C implementation, you must call
1133	/// [`CloseClipboard`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-closeclipboard)
1134	/// as a cleanup operation.
1135	///
1136	/// Here, the cleanup is performed automatically, because `OpenClipboard`
1137	/// returns a [`CloseClipboardGuard`](crate::guard::CloseClipboardGuard),
1138	/// which automatically calls `CloseClipboard` when the guard goes out of
1139	/// scope. You must, however, keep the guard alive, otherwise the cleanup
1140	/// will be performed right away.
1141	///
1142	/// # Examples
1143	///
1144	/// ```no_run
1145	/// use winsafe::{self as w, prelude::*, co};
1146	///
1147	/// let hwnd: w::HWND; // initialized somewhere
1148	/// # let hwnd = w::HWND::NULL;
1149	///
1150	/// let hclip = hwnd.OpenClipboard()?;
1151	/// let data = hclip.GetClipboardData(co::CF::TEXT)?;
1152	/// # w::SysResult::Ok(())
1153	/// ```
1154	///
1155	/// You can also open the clipboard without an `HWND` owner:
1156	///
1157	/// ```no_run
1158	/// use winsafe::{self as w, prelude::*, co};
1159	///
1160	/// let hclip = w::HWND::NULL.OpenClipboard()?;
1161	/// let data = hclip.GetClipboardData(co::CF::TEXT)?;
1162	/// # w::SysResult::Ok(())
1163	/// ```
1164	#[must_use]
1165	pub fn OpenClipboard(&self) -> SysResult<CloseClipboardGuard<'_>> {
1166		unsafe {
1167			bool_to_sysresult(ffi::OpenClipboard(self.ptr()))
1168				.map(|_| CloseClipboardGuard::new(self, HCLIPBOARD::INVALID))
1169		}
1170	}
1171
1172	/// [`PostMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew)
1173	/// function.
1174	///
1175	/// Note that this method is asychronous.
1176	///
1177	/// # Safety
1178	///
1179	/// Messages manipulate pointers, copies and window states. Improper use may
1180	/// lead to undefined behavior.
1181	pub unsafe fn PostMessage<M>(&self, msg: M) -> SysResult<()>
1182	where
1183		M: MsgSend + Send + Copy + 'static,
1184	{
1185		let mut msg = msg;
1186		let wm_any = msg.as_generic_wm();
1187		bool_to_sysresult(unsafe {
1188			ffi::PostMessageW(self.ptr(), wm_any.msg_id.raw(), wm_any.wparam, wm_any.lparam)
1189		})
1190	}
1191
1192	/// [`RealChildWindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-realchildwindowfrompoint)
1193	/// function.
1194	#[must_use]
1195	pub fn RealChildWindowFromPoint(&self, pt_parent_client_coords: POINT) -> Option<HWND> {
1196		ptr_to_option_handle(unsafe {
1197			ffi::RealChildWindowFromPoint(
1198				self.ptr(),
1199				pt_parent_client_coords.x,
1200				pt_parent_client_coords.y,
1201			)
1202		})
1203	}
1204
1205	/// [`RealGetWindowClass`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-realgetwindowclassw)
1206	/// function.
1207	#[must_use]
1208	pub fn RealGetWindowClass(&self) -> SysResult<String> {
1209		let mut buf = WString::new_alloc_buf(256 + 1); // according to WNDCLASSEX docs
1210		bool_to_sysresult(unsafe {
1211			ffi::RealGetWindowClassW(self.ptr(), buf.as_mut_ptr(), buf.buf_len() as _)
1212		} as _)
1213		.map(|_| buf.to_string())
1214	}
1215
1216	/// [`RedrawWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-redrawwindow)
1217	/// function.
1218	pub fn RedrawWindow(
1219		&self,
1220		rc_update: RECT,
1221		hrgn_update: &HRGN,
1222		flags: co::RDW,
1223	) -> SysResult<()> {
1224		bool_to_sysresult(unsafe {
1225			ffi::RedrawWindow(self.ptr(), pcvoid(&rc_update), hrgn_update.ptr(), flags.raw())
1226		})
1227	}
1228
1229	/// [`RegisterHotKey`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey)
1230	/// function.
1231	pub fn RegisterHotKey(&self, id: i32, modifiers: co::MOD, vkey_code: co::VK) -> SysResult<()> {
1232		bool_to_sysresult(unsafe {
1233			ffi::RegisterHotKey(self.ptr(), id, modifiers.raw() as _, vkey_code.raw() as _)
1234		})
1235	}
1236
1237	/// [`ScreenToClient`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-screentoclient)
1238	/// function.
1239	///
1240	/// If you need to convert a [`RECT`](crate::RECT), see the
1241	/// [`HWND::ScreenToClientRc`](crate::HWND::ScreenToClientRc) function.
1242	#[must_use]
1243	pub fn ScreenToClient(&self, pt: POINT) -> SysResult<POINT> {
1244		let mut buf = pt;
1245		bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf)) }).map(|_| buf)
1246	}
1247
1248	/// [`ScreenToClient`](crate::HWND::ScreenToClient) method for a
1249	/// [`RECT`](crate::RECT).
1250	#[must_use]
1251	pub fn ScreenToClientRc(&self, rc: RECT) -> SysResult<RECT> {
1252		let mut buf = rc;
1253		bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf.left)) })?;
1254		bool_to_sysresult(unsafe { ffi::ScreenToClient(self.ptr(), pvoid(&mut buf.right)) })
1255			.map(|_| buf)
1256	}
1257
1258	/// [`ScrollWindowEx`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-scrollwindowex)
1259	/// function.
1260	pub fn ScrollWindowEx(
1261		&self,
1262		dx: i32,
1263		dy: i32,
1264		client_area_portion: Option<&RECT>,
1265		clipping_rect: Option<&RECT>,
1266		hrgn_update: Option<&HRGN>,
1267		updated_boundaries: Option<&mut RECT>,
1268		flags: co::SCROLLW,
1269	) -> SysResult<co::REGION> {
1270		match unsafe {
1271			ffi::ScrollWindowEx(
1272				self.ptr(),
1273				dx,
1274				dy,
1275				pcvoid_or_null(client_area_portion),
1276				pcvoid_or_null(clipping_rect),
1277				hrgn_update.map_or(std::ptr::null_mut(), |h| h.ptr()),
1278				pvoid_or_null(updated_boundaries),
1279				flags.raw(),
1280			)
1281		} {
1282			0 => Err(GetLastError()),
1283			v => Ok(unsafe { co::REGION::from_raw(v) }),
1284		}
1285	}
1286
1287	/// [`SendMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew)
1288	/// function, specialized to send a [`wm::Command`](crate::msg::wm::Command)
1289	/// message.
1290	///
1291	/// Unlike the general [`SendMessage`](crate::HWND::SendMessage), sending a
1292	/// command is safe.
1293	///
1294	/// # Examples
1295	///
1296	/// ```no_run
1297	/// use winsafe::{self as w, prelude::*, msg};
1298	///
1299	/// let hwnd: w::HWND; // initialized somewhere
1300	/// # let hwnd = w::HWND::NULL;
1301	///
1302	/// const ID_MENU_FILE_OPEN: u16 = 103;
1303	///
1304	/// hwnd.SendCommand(
1305	///     w::AccelMenuCtrl::Menu(ID_MENU_FILE_OPEN),
1306	/// );
1307	/// ```
1308	pub fn SendCommand(&self, cmd: AccelMenuCtrl) {
1309		unsafe {
1310			self.SendMessage(wm::Command { event: cmd });
1311		}
1312	}
1313
1314	/// [`SendMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew)
1315	/// function.
1316	///
1317	/// The return type is variable, being defined by the `RetType` associated
1318	/// type of the [`MsgSend`](crate::prelude::MsgSend) trait. That means each
1319	/// message can define its own return type.
1320	///
1321	/// # Safety
1322	///
1323	/// Messages manipulate pointers, copies and window states. Improper use may
1324	/// lead to undefined behavior.
1325	///
1326	/// # Examples
1327	///
1328	/// Sending a [`bm::GetImage`](crate::msg::bm::GetImage) button message,
1329	/// which demands an image type parameter. Note that this specific message
1330	/// can also return an error, which is handled with
1331	/// [`?`](https://doc.rust-lang.org/std/result/index.html#the-question-mark-operator-):
1332	///
1333	/// ```no_run
1334	/// use winsafe::{self as w, prelude::*, co, msg};
1335	///
1336	/// let hwnd: w::HWND; // initialized somewhere
1337	/// # let hwnd = w::HWND::NULL;
1338	///
1339	/// let bmp = unsafe {
1340	///     hwnd.SendMessage(
1341	///         msg::bm::GetImage {
1342	///             img_type: co::IMAGE_TYPE::BITMAP,
1343	///         },
1344	///     )
1345	/// }?;
1346	/// # w::SysResult::Ok(())
1347	/// ```
1348	///
1349	/// Sending an [`em::CharFromPos`](crate::msg::em::CharFromPos) edit message,
1350	/// which receives point coordinates and returns two values:
1351	///
1352	/// ```no_run
1353	/// use winsafe::{self as w, prelude::*, msg};
1354	///
1355	/// let hwnd: w::HWND; // initialized somewhere
1356	/// # let hwnd = w::HWND::NULL;
1357	///
1358	/// let (char_pos, line_pos) = unsafe {
1359	///     hwnd.SendMessage(
1360	///         msg::em::CharFromPos {
1361	///             coords: w::POINT::with(12, 20),
1362	///         },
1363	///     )
1364	/// };
1365	/// ```
1366	pub unsafe fn SendMessage<M>(&self, msg: M) -> M::RetType
1367	where
1368		M: MsgSend,
1369	{
1370		let mut msg = msg;
1371		let wm_any = msg.as_generic_wm();
1372		unsafe {
1373			msg.isize_to_ret(ffi::SendMessageW(
1374				self.ptr(),
1375				wm_any.msg_id.raw(),
1376				wm_any.wparam,
1377				wm_any.lparam,
1378			))
1379		}
1380	}
1381
1382	/// [`SendMessageTimeout`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagetimeoutw)
1383	/// function.
1384	///
1385	/// # Safety
1386	///
1387	/// Messages manipulate pointers, copies and window states. Improper use may
1388	/// lead to undefined behavior.
1389	pub unsafe fn SendMessageTimeout<M>(
1390		&self,
1391		msg: M,
1392		flags: co::SMTO,
1393		timeout_ms: u32,
1394	) -> SysResult<M::RetType>
1395	where
1396		M: MsgSend,
1397	{
1398		let mut msg = msg;
1399		let wm_any = msg.as_generic_wm();
1400		let mut result = 0isize;
1401
1402		unsafe {
1403			bool_to_sysresult(ffi::SendMessageTimeoutW(
1404				self.ptr(),
1405				wm_any.msg_id.raw(),
1406				wm_any.wparam,
1407				wm_any.lparam,
1408				flags.raw(),
1409				timeout_ms,
1410				&mut result,
1411			) as _)
1412			.map(|_| msg.isize_to_ret(result))
1413		}
1414	}
1415
1416	/// [`SetActiveWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setactivewindow)
1417	/// function.
1418	pub fn SetActiveWindow(&self) -> SysResult<HWND> {
1419		ptr_to_sysresult_handle(unsafe { ffi::SetActiveWindow(self.ptr()) })
1420	}
1421
1422	/// [`SetCapture`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcapture)
1423	/// function.
1424	pub fn SetCapture(&self) -> ReleaseCaptureGuard<'_> {
1425		unsafe {
1426			ReleaseCaptureGuard::new(
1427				self,
1428				ffi::SetCapture(self.ptr())
1429					.as_mut()
1430					.map(|ptr| HWND::from_ptr(ptr)),
1431			)
1432		}
1433	}
1434
1435	/// [`SetDialogDpiChangeBehavior`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setdialogdpichangebehavior)
1436	/// function.
1437	pub fn SetDialogDpiChangeBehavior(&self, mask: co::DDC, values: co::DDC) -> SysResult<()> {
1438		bool_to_sysresult(unsafe {
1439			ffi::SetDialogDpiChangeBehavior(self.ptr(), mask.raw(), values.raw())
1440		})
1441	}
1442
1443	/// [`SetFocus`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setfocus)
1444	/// function.
1445	pub fn SetFocus(&self) -> Option<HWND> {
1446		ptr_to_option_handle(unsafe { ffi::SetFocus(self.ptr()) })
1447	}
1448
1449	/// [`SetForegroundWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow)
1450	/// function.
1451	pub fn SetForegroundWindow(&self) -> bool {
1452		unsafe { ffi::SetForegroundWindow(self.ptr()) != 0 }
1453	}
1454
1455	/// [`SetLayeredWindowAttributes`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setlayeredwindowattributes)
1456	/// function.
1457	pub fn SetLayeredWindowAttributes(
1458		&self,
1459		transparency_color_key: COLORREF,
1460		alpha: u8,
1461		flags: co::LWA,
1462	) -> SysResult<()> {
1463		bool_to_sysresult(unsafe {
1464			ffi::SetLayeredWindowAttributes(
1465				self.ptr(),
1466				transparency_color_key.raw(),
1467				alpha,
1468				flags.raw(),
1469			)
1470		})
1471	}
1472
1473	/// [`SetMenu`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setmenu)
1474	/// function.
1475	pub fn SetMenu(&self, hmenu: &HMENU) -> SysResult<()> {
1476		bool_to_sysresult(unsafe { ffi::SetMenu(self.ptr(), hmenu.ptr()) })
1477	}
1478
1479	/// [`SetParent`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent)
1480	/// function.
1481	pub fn SetParent(&self, hwnd_new_parent: &HWND) -> SysResult<Option<HWND>> {
1482		match ptr_to_option_handle(unsafe { ffi::SetParent(self.ptr(), hwnd_new_parent.ptr()) }) {
1483			None => match GetLastError() {
1484				co::ERROR::SUCCESS => Ok(None), // no previous parent
1485				err => Err(err),
1486			},
1487			Some(h) => Ok(Some(h)),
1488		}
1489	}
1490
1491	/// [`SetScrollInfo`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollinfo)
1492	/// function.
1493	pub fn SetScrollInfo(&self, bar: co::SBB, si: &SCROLLINFO, redraw: bool) -> i32 {
1494		unsafe { ffi::SetScrollInfo(self.ptr(), bar.raw(), pcvoid(si), redraw as _) }
1495	}
1496
1497	/// [`SetScrollPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollpos)
1498	/// function.
1499	pub fn SetScrollPos(&self, b: co::SBB, pos: i32, redraw: bool) -> SysResult<i32> {
1500		match unsafe { ffi::SetScrollPos(self.ptr(), b.raw(), pos, redraw as _) } {
1501			0 => match GetLastError() {
1502				co::ERROR::SUCCESS => Ok(0), // actual zero position
1503				err => Err(err),
1504			},
1505			pos => Ok(pos),
1506		}
1507	}
1508
1509	/// [`SetScrollRange`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollrange)
1510	/// function.
1511	pub fn SetScrollRange(
1512		&self,
1513		bar: co::SBB,
1514		min_pos: i32,
1515		max_pos: i32,
1516		redraw: bool,
1517	) -> SysResult<()> {
1518		bool_to_sysresult(unsafe {
1519			ffi::SetScrollRange(self.ptr(), bar.raw(), min_pos, max_pos, redraw as _)
1520		})
1521	}
1522
1523	/// This method returns the timer ID, to be passed to
1524	/// [`HWND::KillTimer`](crate::HWND::KillTimer).
1525	///
1526	/// The timer calls – either
1527	/// [`wm_timer`](crate::gui::events::WindowEvents::wm_timer) message or
1528	/// callback function – will continuously be executed until you call
1529	/// `KillTimer`. If you don't call `KillTimer`, the timer calls will
1530	/// continue until the window is destroyed – at this point, any remaining
1531	/// timers will be automatically cleared.
1532	///
1533	/// # Why not closures?
1534	///
1535	/// A common C++ technique to use closures with `SetTimer` is allocating a
1536	/// closure on the heap and use its pointer as the timer ID. When the
1537	/// callback function is called, the pointer is dereferenced and the closure
1538	/// is then executed.
1539	///
1540	/// The problem with this approach is that the closure must be freed after
1541	/// `KillTimer`, which can be called from anywhere, including from the
1542	/// closure itself – that means you must keep the pointer outside the
1543	/// closure and free it somehow after the closure finishes.
1544	///
1545	/// Such approach is, obviously, incredibly unsafe, and only possible within
1546	/// Rust's rigid ownership rules if we use some sort of garbage-collection,
1547	/// which will free the allocated closure some time after `KillTimer` is
1548	/// called and the closure itself finishes. Since that would incur in a
1549	/// performance penalty, the current implementation of `SetTimer` will only
1550	/// accept ordinary function pointers, not closures.
1551	///
1552	/// Handling the `wm_timer` message is simply more practical and efficient,
1553	/// so the use of a callback is discouraged here.
1554	pub fn SetTimer(
1555		&self,
1556		event_id: usize,
1557		elapse_ms: u32,
1558		timer_func: Option<TIMERPROC>,
1559	) -> SysResult<usize> {
1560		match unsafe {
1561			ffi::SetTimer(
1562				self.ptr(),
1563				event_id,
1564				elapse_ms,
1565				timer_func.map_or(std::ptr::null(), |lp| lp as _),
1566			)
1567		} {
1568			0 => Err(GetLastError()),
1569			tid => Ok(tid),
1570		}
1571	}
1572
1573	/// [`SetWindowDisplayAffinity`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity)
1574	/// function.
1575	pub fn SetWindowDisplayAffinity(&self, affinity: co::WDA) -> SysResult<()> {
1576		bool_to_sysresult(unsafe { ffi::SetWindowDisplayAffinity(self.ptr(), affinity.raw()) })
1577	}
1578
1579	/// [`SetWindowLongPtr`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlongptrw)
1580	/// function.
1581	///
1582	/// If you just want to set the window styles, prefer using
1583	/// [`HWND::set_style`](crate::HWND::set_style) and
1584	/// [`HWND::set_style_ex`](crate::HWND::set_style_ex).
1585	///
1586	/// # Safety
1587	///
1588	/// Changing these values may potentially cause undefined behavior to the
1589	/// window, and passed pointers must be handled correctly.
1590	pub unsafe fn SetWindowLongPtr(&self, index: co::GWLP, new_long: isize) -> isize {
1591		#[cfg(target_pointer_width = "32")]
1592		unsafe {
1593			ffi::SetWindowLongW(self.ptr(), index.raw(), new_long)
1594		}
1595
1596		#[cfg(target_pointer_width = "64")]
1597		unsafe {
1598			ffi::SetWindowLongPtrW(self.ptr(), index.raw(), new_long)
1599		}
1600	}
1601
1602	/// [`SetWindowPlacement`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowplacement)
1603	/// function.
1604	pub fn SetWindowPlacement(&self, wp: &WINDOWPLACEMENT) -> SysResult<()> {
1605		bool_to_sysresult(unsafe { ffi::SetWindowPlacement(self.ptr(), pcvoid(wp)) })
1606	}
1607
1608	/// [`SetWindowPos`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos)
1609	/// function.
1610	///
1611	/// # Examples
1612	///
1613	/// ```no_run
1614	/// use winsafe::{self as w, prelude::*, co};
1615	///
1616	/// let hwnd: w::HWND; // initialized somewhere
1617	/// # let hwnd = w::HWND::NULL;
1618	///
1619	/// hwnd.SetWindowPos(
1620	///     w::HwndPlace::None,
1621	///     w::POINT::with(10, 10),
1622	///     w::SIZE::default(),
1623	///     co::SWP::NOZORDER | co::SWP::NOSIZE,
1624	/// )?;
1625	/// # w::SysResult::Ok(())
1626	/// ```
1627	pub fn SetWindowPos(
1628		&self,
1629		hwnd_insert_after: HwndPlace,
1630		pos: POINT,
1631		size: SIZE,
1632		flags: co::SWP,
1633	) -> SysResult<()> {
1634		bool_to_sysresult(unsafe {
1635			ffi::SetWindowPos(
1636				self.ptr(),
1637				hwnd_insert_after.as_ptr(),
1638				pos.x,
1639				pos.y,
1640				size.cx,
1641				size.cy,
1642				flags.raw(),
1643			)
1644		})
1645	}
1646
1647	/// [`SetWindowRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowrgn)
1648	/// function.
1649	pub fn SetWindowRgn(&self, hrgn: &HRGN, redraw: bool) -> SysResult<()> {
1650		bool_to_sysresult(unsafe { ffi::SetWindowRgn(self.ptr(), hrgn.ptr(), redraw as _) })
1651	}
1652
1653	/// [`SetWindowText`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw)
1654	/// function.
1655	pub fn SetWindowText(&self, text: &str) -> SysResult<()> {
1656		bool_to_sysresult(unsafe {
1657			ffi::SetWindowTextW(self.ptr(), WString::from_str(text).as_ptr())
1658		})
1659	}
1660
1661	/// [`ShowCaret`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showcaret)
1662	/// function.
1663	pub fn ShowCaret(&self) -> SysResult<()> {
1664		bool_to_sysresult(unsafe { ffi::ShowCaret(self.ptr()) })
1665	}
1666
1667	/// [`ShowOwnedPopups`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showownedpopups)
1668	/// function.
1669	pub fn ShowOwnedPopups(&self, show: bool) -> SysResult<()> {
1670		bool_to_sysresult(unsafe { ffi::ShowOwnedPopups(self.ptr(), show as _) })
1671	}
1672
1673	/// [`ShowWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow)
1674	/// function.
1675	pub fn ShowWindow(&self, show_cmd: co::SW) -> bool {
1676		unsafe { ffi::ShowWindow(self.ptr(), show_cmd.raw()) != 0 }
1677	}
1678
1679	/// [`ShowWindowAsync`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindowasync)
1680	/// function.
1681	pub fn ShowWindowAsync(&self, show_cmd: co::SW) -> SysResult<()> {
1682		bool_to_sysresult(unsafe { ffi::ShowWindowAsync(self.ptr(), show_cmd.raw()) })
1683	}
1684
1685	/// [`ShutdownBlockReasonCreate`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasoncreate)
1686	/// function.
1687	pub fn ShutdownBlockReasonCreate(&self, reason: &str) -> SysResult<()> {
1688		bool_to_sysresult(unsafe {
1689			ffi::ShutdownBlockReasonCreate(self.ptr(), WString::from_str(reason).as_ptr())
1690		})
1691	}
1692
1693	/// [`ShutdownBlockReasonDestroy`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasondestroy)
1694	/// function.
1695	pub fn ShutdownBlockReasonDestroy(&self) -> SysResult<()> {
1696		bool_to_sysresult(unsafe { ffi::ShutdownBlockReasonDestroy(self.ptr()) })
1697	}
1698
1699	/// [`ShutdownBlockReasonQuery`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-shutdownblockreasonquery)
1700	/// function.
1701	#[must_use]
1702	pub fn ShutdownBlockReasonQuery(&self) -> SysResult<String> {
1703		let mut sz = 0u32;
1704		bool_to_sysresult(unsafe {
1705			ffi::ShutdownBlockReasonQuery(self.ptr(), std::ptr::null_mut(), &mut sz)
1706		})?;
1707
1708		let mut buf = WString::new_alloc_buf(sz as _);
1709		bool_to_sysresult(unsafe {
1710			ffi::ShutdownBlockReasonQuery(self.ptr(), buf.as_mut_ptr(), &mut sz)
1711		})
1712		.map(|_| buf.to_string())
1713	}
1714
1715	/// [`TileWindows`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-tilewindows)
1716	/// function.
1717	pub fn TileWindows(
1718		&self,
1719		how: co::MDITILE,
1720		rect: Option<RECT>,
1721		kids: &[&HWND],
1722	) -> SysResult<u16> {
1723		match unsafe {
1724			ffi::TileWindows(
1725				self.ptr(),
1726				how.raw(),
1727				pcvoid_or_null(rect.as_ref()),
1728				kids.len() as _,
1729				vec_ptr(kids) as _,
1730			)
1731		} {
1732			0 => match GetLastError() {
1733				co::ERROR::SUCCESS => Ok(0),
1734				err => Err(err),
1735			},
1736			c => Ok(c),
1737		}
1738	}
1739
1740	/// [`TranslateAccelerator`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translateacceleratorw)
1741	/// function.
1742	pub fn TranslateAccelerator(&self, haccel_table: &HACCEL, msg: &mut MSG) -> SysResult<()> {
1743		bool_to_sysresult(unsafe {
1744			ffi::TranslateAcceleratorW(self.ptr(), haccel_table.ptr(), pvoid(msg))
1745		})
1746	}
1747
1748	/// [`UnregisterHotKey`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-unregisterhotkey)
1749	/// function.
1750	pub fn UnregisterHotKey(&self, id: i32) -> SysResult<()> {
1751		bool_to_sysresult(unsafe { ffi::UnregisterHotKey(self.ptr(), id) })
1752	}
1753
1754	/// [`UpdateLayeredWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatelayeredwindow)
1755	/// function.
1756	pub fn UpdateLayeredWindow(
1757		&self,
1758		hdc_dest: Option<&HDC>,
1759		pt_dest: Option<&POINT>,
1760		size: Option<&SIZE>,
1761		hdc_src: Option<&HDC>,
1762		pt_src: Option<&POINT>,
1763		key: COLORREF,
1764		blend: &BLENDFUNCTION,
1765		flags: co::ULW,
1766	) -> SysResult<()> {
1767		bool_to_sysresult(unsafe {
1768			ffi::UpdateLayeredWindow(
1769				self.ptr(),
1770				hdc_dest.map_or(std::ptr::null_mut(), |hdc| hdc.ptr()),
1771				pcvoid_or_null(pt_dest),
1772				pcvoid_or_null(size),
1773				hdc_src.map_or(std::ptr::null_mut(), |hdc| hdc.ptr()),
1774				pcvoid_or_null(pt_src),
1775				key.raw(),
1776				pcvoid(blend),
1777				flags.raw(),
1778			)
1779		})
1780	}
1781
1782	/// [`UpdateWindow`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow)
1783	/// function.
1784	pub fn UpdateWindow(&self) -> SysResult<()> {
1785		bool_to_sysresult(unsafe { ffi::UpdateWindow(self.ptr()) })
1786	}
1787
1788	/// [`ValidateRect`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-validaterect)
1789	/// function.
1790	pub fn ValidateRect(&self, rc: Option<RECT>) -> SysResult<()> {
1791		bool_to_sysresult(unsafe { ffi::ValidateRect(self.ptr(), pcvoid_or_null(rc.as_ref())) })
1792	}
1793
1794	/// [`ValidateRgn`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-validatergn)
1795	/// function.
1796	pub fn ValidateRgn(&self, hrgn: &HRGN) -> SysResult<()> {
1797		bool_to_sysresult(unsafe { ffi::ValidateRgn(self.ptr(), hrgn.ptr()) })
1798	}
1799
1800	/// [`WindowFromPhysicalPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-windowfromphysicalpoint)
1801	/// function.
1802	#[must_use]
1803	pub fn WindowFromPhysicalPoint(pt: POINT) -> Option<HWND> {
1804		ptr_to_option_handle(unsafe { ffi::WindowFromPhysicalPoint(pt.x, pt.y) })
1805	}
1806
1807	/// [`WindowFromPoint`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-windowfrompoint)
1808	/// function.
1809	#[must_use]
1810	pub fn WindowFromPoint(pt: POINT) -> Option<HWND> {
1811		ptr_to_option_handle(unsafe { ffi::WindowFromPoint(pt.x, pt.y) })
1812	}
1813
1814	/// [`WinHelp`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-winhelpw)
1815	/// function.
1816	pub fn WinHelp(&self, help_file: &str, cmd: co::HELPW, data: usize) -> SysResult<()> {
1817		bool_to_sysresult(unsafe {
1818			ffi::WinHelpW(self.ptr(), WString::from_str(help_file).as_ptr(), cmd.raw(), data)
1819		})
1820	}
1821}